// #pragma once

// #include "Thread.hpp"
// #include "LockGuard.hpp"
// #include <vector>
// #include <queue>
// #include <pthread.h>
// #include <mutex>

// using namespace my_thread;

// using std::cerr;
// using std::cin;
// using std::cout;
// using std::endl;

// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// const int gnum = 5;

// template <class T>
// class ThreadPool;

// template <class T>
// class ThreadData
// {
// public:
//     ThreadData(ThreadPool<T> *tp, const std::string &name)
//         : _threadpool(tp),
//           _name(name)
//     {
//     }
//     ~ThreadData()
//     {
//     }

// public:
//     ThreadPool<T> *_threadpool;
//     std::string _name;
// };

// template <class T>
// class ThreadPool
// {
// public:
//     void mylock()
//     {
//         pthread_mutex_lock(&_mutex);
//     }
//     void myunlock()
//     {
//         pthread_mutex_unlock(&_mutex);
//     }
//     bool myQueueEmpty()
//     {
//         return _task_queue.empty();
//     }
//     void myThreadWait()
//     {
//         pthread_cond_wait(&_cond, &_mutex);
//     }
//     T Pop()
//     {
//         T t = _task_queue.front();
//         _task_queue.pop();
//         return t;
//     }
//     pthread_mutex_t *mutex()
//     {
//         return &_mutex;
//     }

// private:
//     static void *handlerTask(void *args)
//     {
//         ThreadData<T> *td = static_cast<ThreadData<T> *>(args);
//         while (true)
//         {
//             T t;
//             {
//                 LockGuard lockguard(td->_threadpool->mutex()); // RAII —— 要构建临时对象！！！
//                 while (td->_threadpool->myQueueEmpty())
//                 {
//                     td->_threadpool->myThreadWait();
//                 }
//                 t = td->_threadpool->Pop();
//             }
//             cout << td->_name << " 获取了1个任务: " << t.TaskToString() << "处理完的结果是:" << t() << endl;
//         }
//         delete td;
//         return nullptr;
//     }

//     // ThreadPool(const int &num = gnum) ////构造函数要放到private里面 —————— 单例模式还有是个单例呢，不是没有例了！！！
//     //     : _num(num)
//     // {
//     //     pthread_mutex_init(&_mutex, nullptr);
//     //     pthread_cond_init(&_cond, nullptr);
//     //     for (size_t i = 0; i < _num; ++i)
//     //     {
//     //         _threads.push_back(new Thread());
//     //     }
//     // }
//     // // 赋值拷贝还有许多地方要进行研究：支不支持连等，返回值是什么类型的，允不允许自己赋值自己
//     // void operator=(const ThreadPool &) = delete; // 赋值语句要取消！！！！
//     // // 拷贝构造没有void
//     // ThreadPool(const ThreadPool &) = delete; // 拷贝构造要取消！！！！

// public:
//     ThreadPool(const int &num = gnum) ////构造函数要放到private里面 —————— 单例模式还有是个单例呢，不是没有例了！！！
//         : _num(num)
//     {
//         pthread_mutex_init(&_mutex, nullptr);
//         pthread_cond_init(&_cond, nullptr);
//         for (size_t i = 0; i < _num; ++i)
//         {
//             _threads.push_back(new Thread());
//         }
//     }
//     void run()
//     {
//         for (const auto &t : _threads)
//         {
//             ThreadData<T> *td = new ThreadData<T>(this, t->threadname());
//             t->start(handlerTask, td);
//             printf("%s run... \n", t->threadname().c_str());
//         }
//     }
//     void Push(const T &in)
//     {
//         LockGuard lockguard(&_mutex); // RAII —— 要构建临时对象！！！
//         _task_queue.push(in);
//         pthread_cond_signal(&_cond);
//     }
//     ~ThreadPool()
//     {
//         pthread_mutex_destroy(&_mutex);
//         pthread_cond_destroy(&_cond);
//         for (const auto &t : _threads)
//             delete t;
//     }
//     ///////一般一个类内函数，既属于类又属于对象；我们这里加上static，使得函数只属于类，不属于对象！！！
//     static ThreadPool<T> *getInstance() // 单例模式这里可以传参的
//     {
//         if (tp == nullptr) // 增加并发度，不要每一次进来都直接面对申请锁
//         {
//             _singlock.lock();
//             if (tp == nullptr)
//             {
//                 tp = new ThreadPool<T>();
//             }
//             _singlock.unlock();
//         }
//         return tp;
//     }

// private:
//     int _num;
//     std::vector<Thread *> _threads;
//     std::queue<T> _task_queue;
//     pthread_mutex_t _mutex;
//     pthread_cond_t _cond;

//     static ThreadPool<T> *tp; // 要构建一个静态的指针
//     static std::mutex _singlock;
// };

// template <class T> // 静态指针tp的定义
// ThreadPool<T> *ThreadPool<T>::tp = nullptr;

// template <class T>
// std::mutex ThreadPool<T>::_singlock;



#pragma once

#include "Thread.hpp"
#include "LockGuard.hpp"
#include "log.hpp"
#include <vector>
#include <queue>
#include <pthread.h>
#include <mutex>

using namespace my_thread;

using std::cerr;
using std::cin;
using std::cout;
using std::endl;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
const int gnum = 5;

template <class T>
class ThreadPool;

template <class T>
class ThreadData
{
public:
    ThreadData(ThreadPool<T> *tp, const std::string &name)
        : _threadpool(tp),
          _name(name)
    {
    }
    ~ThreadData()
    {
    }

public:
    ThreadPool<T> *_threadpool;
    std::string _name;
};

template <class T>
class ThreadPool
{
public:
    void mylock()
    {
        pthread_mutex_lock(&_mutex);
    }
    void myunlock()
    {
        pthread_mutex_unlock(&_mutex);
    }
    bool myQueueEmpty()
    {
        return _task_queue.empty();
    }
    void myThreadWait()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    T Pop()
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }
    pthread_mutex_t *mutex()
    {
        return &_mutex;
    }

private:
    static void *handlerTask(void *args)
    {
        ThreadData<T> *td = static_cast<ThreadData<T> *>(args);
        while (true)
        {
            T t;
            {
                LockGuard lockguard(td->_threadpool->mutex()); // RAII —— 要构建临时对象！！！
                while (td->_threadpool->myQueueEmpty())
                {
                    td->_threadpool->myThreadWait();
                }
                t = td->_threadpool->Pop();
            }
            t();//回调serverIO
        }
        delete td;
        return nullptr;
    }

    // ThreadPool(const int &num = gnum) ////构造函数要放到private里面 —————— 单例模式还有是个单例呢，不是没有例了！！！
    //     : _num(num)
    // {
    //     pthread_mutex_init(&_mutex, nullptr);
    //     pthread_cond_init(&_cond, nullptr);
    //     for (size_t i = 0; i < _num; ++i)
    //     {
    //         _threads.push_back(new Thread());
    //     }
    // }
    // // 赋值拷贝还有许多地方要进行研究：支不支持连等，返回值是什么类型的，允不允许自己赋值自己
    // void operator=(const ThreadPool &) = delete; // 赋值语句要取消！！！！
    // // 拷贝构造没有void
    // ThreadPool(const ThreadPool &) = delete; // 拷贝构造要取消！！！！

public:
    ThreadPool(const int &num = gnum) ////构造函数要放到private里面 —————— 单例模式还有是个单例呢，不是没有例了！！！
        : _num(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        for (size_t i = 0; i < _num; ++i)
        {
            _threads.push_back(new Thread());
        }
    }
    void run()
    {
        for (const auto &t : _threads)
        {
            ThreadData<T> *td = new ThreadData<T>(this, t->threadname());
            t->start(handlerTask, td);
            //printf("%s run... \n", t->threadname().c_str());
            logMessage(DEBUG,"%s run...",t->threadname().c_str());
        }
    }
    void Push(const T &in)
    {
        LockGuard lockguard(&_mutex); // RAII —— 要构建临时对象！！！
        _task_queue.push(in);
        pthread_cond_signal(&_cond);
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (const auto &t : _threads)
            delete t;
    }
    ///////一般一个类内函数，既属于类又属于对象；我们这里加上static，使得函数只属于类，不属于对象！！！
    static ThreadPool<T> *getInstance() // 单例模式这里可以传参的
    {
        if (tp == nullptr) // 增加并发度，不要每一次进来都直接面对申请锁
        {
            _singlock.lock();
            if (tp == nullptr)
            {
                tp = new ThreadPool<T>();
            }
            _singlock.unlock();
        }
        return tp;
    }

private:
    int _num;
    std::vector<Thread *> _threads;
    std::queue<T> _task_queue;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

    static ThreadPool<T> *tp; // 要构建一个静态的指针
    static std::mutex _singlock;
};

template <class T> // 静态指针tp的定义
ThreadPool<T> *ThreadPool<T>::tp = nullptr;

template <class T>
std::mutex ThreadPool<T>::_singlock;